import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { MenuEntity } from './menu.entity';
import { Between, Not, TreeRepository, getManager, Brackets } from 'typeorm';
import * as dayjs from 'dayjs';
// import { skip } from 'rxjs/operators';


@Injectable()
export class MenuService {
  constructor(
    @InjectRepository(MenuEntity)
    private readonly menuRepository: Repository<MenuEntity>,
  ) {}

  async getMenuList(param) {
    return await this.menuRepository.find({ where: param });
  }
  async getMenuTreeList(param) {
    const {
      current,
      pageSize,
      noPagination,
      orderParam,
      createDateRange,
      accessIds,
      ...restParam
    } = param;

    let where = {
      ...restParam,
      createDate: Between(createDateRange?.[0], createDateRange?.[1]),
    };
    if (!createDateRange) {
      delete where.createDate;
    }

    //排序逻辑
    const order = {};
    Object.keys(orderParam || {}).map(item => {
      order[`menu.${item}`] = orderParam[item];
    });
    const manager = getManager();
    let data = await manager
      .getTreeRepository(MenuEntity)
      .createDescendantsQueryBuilder('menu', 'menuClosure', new MenuEntity())
      .leftJoinAndSelect('menu.access', 'access')
      .leftJoinAndSelect('menu.children', 'children')
      .where(where)
      .andWhere({ type: 1 })
      .andWhere(qb => {
        const subQuery = qb
          .subQuery()
          .select('menu.id')
          .from(MenuEntity, 'menu')
          .leftJoin('menu.access', 'access')
          .andWhere(
            new Brackets(qb => {
              if (accessIds) {
                return qb.where('access.id IN (:...accessIds)', { accessIds });
              }
            }),
          )
          .getQuery();
        return 'menu.id IN ' + subQuery;
      })
      .orderBy(order)
      .skip(noPagination ? undefined : (current - 1) * pageSize)
      .take(noPagination ? undefined : pageSize)
      .getManyAndCount();
    return { data: data[0], total: data[1], current, pageSize };
  }

  async getMenuTree(param) {
    const manager = getManager();
    return await manager
      .getTreeRepository(MenuEntity)
      .findTrees({ relations: ['access'] });
  }
  async getMenu(param) {
    return await this.menuRepository
      .createQueryBuilder('menu')
      .leftJoinAndSelect('menu.access', 'access')
      .where(param)
      .getOne();
  }
  async saveMenu(param) {
    const { pid, access = [], ...restParam } = param;
    const manager = getManager();
    let menu = new MenuEntity();
    Object.assign(menu, restParam);
    // menu.access = access.map(id => {
    //   return { id };
    // });
    !menu.id && (menu.createDate = dayjs().format('YYYY-MM-DD HH:mm:ss'));
    if (pid) {
      const root = new MenuEntity();
      root.id = pid;
      menu.parent = root;
      return await manager.save(menu);
    } else {
      return await manager.save(menu);
    }
  }
  async delMenuList(param) {
    const { idList } = param;
    let data = await this.menuRepository.findByIds(idList);
    return await this.menuRepository.remove(data);
  }
}
